#pragma once

#include <iostream>
#include <ctime>
#include <cerrno>
#include <cstring>

namespace micromq
{
    #define DEBUG_LEVEL 0
    #define INFO_LEVEL 1
    #define ERROR_LEVEL 2
    #define DEFAULT_LEVEL DEBUG_LEVEL

    #define logger(level, levelName, format, ...)                                                                    \
    {                                                                                                                \
        if(level >= DEFAULT_LEVEL)                                                                                   \
        {                                                                                                            \
            time_t cur_time = time(nullptr);                                                                         \
            struct tm* tm = localtime(&cur_time);                                                                    \
            char time_buffer[128];                                                                                   \
            strftime(time_buffer, 31, "%Y/%m/%d %H:%M.%S", tm);                                                      \
            if(level == ERROR_LEVEL)                                                                                 \
            {                                                                                                        \
                printf("[%s][%s][%s:%d] " format " [%d: %s]\n",                                                      \
                    levelName, time_buffer, __FILE__, __LINE__, ##__VA_ARGS__, errno, strerror(errno));              \
            }                                                                                                        \
            else                                                                                                     \
            {                                                                                                        \
                printf("[%s][%s][%s:%d] " format "\n", levelName, time_buffer, __FILE__, __LINE__, ##__VA_ARGS__);   \
            }                                                                                                        \
        }                                                                                                            \
    }

    #define logDebug(format, ...) logger(DEBUG_LEVEL, "debug", format, ##__VA_ARGS__)
    #define logInfo(format, ...) logger(INFO_LEVEL, "info ", format, ##__VA_ARGS__)
    #define logError(format, ...) logger(ERROR_LEVEL, "error", format, ##__VA_ARGS__)

    #define markc(format, ...)                                                                                       \
    {                                                                                                                \
        printf("***** " format " *****\n", ##__VA_ARGS__);                                                           \
    }

    #define markcc std::cout << "***** "
    #define enter " *****" << std::endl
}